
import { Path, Shape, ShapeUtils, Vector2, Vector3 } from "three";
import { AK, EntityCreateType } from "../const/ModelConst";
import AModelFmulaUtils from "./AModelFmulaUtils";
import { BIM } from "./BIM";
import VectorUtils from "./VectorUtils";

export default class CommonUtils {

    static sjHoles(data: any, W: number, H: number, p_kbj: number, yval: number, iswall: boolean = false) {
        let sjholes = [];
        let kongpoint = [];
        let xv: number, yv: number, i: number;
        let holePath: Path;
        if (!iswall) {
            sjholes = [];

            let zspkfa = AModelFmulaUtils.getHolesbyExpress(data[AK.p_zspkfa], W, 2, null, null, 10008);
            let yspkfa = AModelFmulaUtils.getHolesbyExpress(data[AK.p_yspkfa], H, 2, null, null, 10008);

            for (i = 0; i < zspkfa.length; i++) {

                xv = p_kbj;
                yv = zspkfa[i];

                holePath = new Path()
                    .moveTo(xv, yv)
                    .absarc(xv, yv, data.BKDia / 2, 0, Math.PI * 2, true);

                sjholes.push(holePath);

                kongpoint.push(xv, yval, yv);
            }

            for (i = 0; i < yspkfa.length; i++) {

                xv = yspkfa[i];
                yv = p_kbj;

                holePath = new Path()
                    .moveTo(xv, yv)
                    .absarc(xv, yv, data.BKDia / 2, 0, Math.PI * 2, true);

                sjholes.push(holePath);

                kongpoint.push(xv, yval, yv);
            }
        }

        return [sjholes, kongpoint];
    }

    static megreAry(oneAry: string[], twoAry: any[]): any[] {
        let tmpAry = [...oneAry, ...twoAry];
        return [... new Set(tmpAry)];
    }

    static formStringToArray(str: string) {
        let strArr = str.split(")");
        let numArr = [];

        for (let i = 0; i < strArr.length; i++) {
            if (strArr[i] != "") {
                let match = strArr[i].match(/-?\d+/g);
                if (match && match.length > 1) {
                    let num1 = parseInt(match[0]);
                    let num2 = parseInt(match[1]);
                    numArr.push([num1, num2]);
                }

            }
        }

        return numArr;
    }

    static getStrAry(str: string): string[] {
        let strAry = this.formStringToArray(str);
        let result: string[] = [];
        for (let i = 0; i < strAry.length; i++) {
            result.push('(' + strAry[i][0] + ',' + strAry[i][1] + ')')
        }
        return result;
    }

    static mergeFaceHole(userData: any, lgkr: number, lgkdw: string, type: number = 0) {

        let changeobj = {};

        let p_r1 = type == 1 ? AK.p_l_r1 : type == 2 ? AK.p_r_r1 : type == 3 ? AK.p_t_r1 : type == 4 ? AK.p_tl_r1 : type == 5 ? AK.p_tr_r1 : AK.p_r1;
        let p_r1dw = type == 1 ? AK.p_l_r1dw : type == 2 ? AK.p_r_r1dw : type == 3 ? AK.p_t_r1dw : type == 4 ? AK.p_tl_r1dw : type == 5 ? AK.p_tr_r1dw : AK.p_r1dw;
        let p_r2 = type == 1 ? AK.p_l_r2 : type == 2 ? AK.p_r_r2 : type == 3 ? AK.p_t_r2 : type == 4 ? AK.p_tl_r2 : type == 5 ? AK.p_tr_r2 : AK.p_r2;
        let p_r2dw = type == 1 ? AK.p_l_r2dw : type == 2 ? AK.p_r_r2dw : type == 3 ? AK.p_t_r2dw : type == 4 ? AK.p_tl_r2dw : type == 5 ? AK.p_tr_r2dw : AK.p_r2dw;
        let p_r3 = type == 1 ? AK.p_l_r3 : type == 2 ? AK.p_r_r3 : type == 3 ? AK.p_t_r3 : type == 4 ? AK.p_tl_r3 : type == 5 ? AK.p_tr_r3 : AK.p_r3;
        let p_r3dw = type == 1 ? AK.p_l_r3dw : type == 2 ? AK.p_r_r3dw : type == 3 ? AK.p_t_r3dw : type == 4 ? AK.p_tl_r3dw : type == 5 ? AK.p_tr_r3dw : AK.p_r3dw;

        // 原始的 r1 r1dw
        let or = userData[p_r1];
        let ordw = userData[p_r1dw];
        if (!or && !ordw) {
            changeobj[p_r1] = lgkr;
            changeobj[p_r1dw] = lgkdw;
            return changeobj;
        }
        // 螺杆孔定位
        let lgkAry = this.getStrAry(lgkdw);

        let or1 = Number(or);

        // 原始孔位
        let or1dwAry: string[] = this.getStrAry(userData[p_r1dw])
        // 获取后台孔位
        changeobj[p_r1] = lgkr.toString();
        if (Math.abs(lgkr - or1) < 0.001) {
            // 认为两个孔位相等,就把后台孔和面板孔合并
            let mergedata = this.megreAry(or1dwAry, lgkAry).join(',');
            changeobj[p_r1dw] = mergedata
        }
        else {
            changeobj[p_r1dw] = lgkdw.toString();
            // r1孔位不相等, r1去挤r2
            if (userData[p_r2] && userData[p_r2] != '') {
                // r2 不为空， 比较下r1 跟 r2是否相等
                let or2 = Number(userData[p_r2]);
                if (Math.abs(or2 - or1) < 0.001) {
                    // 认为r2 跟 r1 相等， 开始合并定位
                    let or2dwAry = this.getStrAry(userData[p_r2dw]);
                    changeobj[p_r2dw] = this.megreAry(or2dwAry, or1dwAry).join(',');
                }
                else {
                    // r1 和 r2 不相等，找r3
                    if (userData[p_r3] && userData[p_r3] != '') {
                        let or3 = Number(userData[p_r3]);
                        if (Math.abs(or3 - or1) < 0.001) {
                            // 认为r3 跟 r1 相等， 开始合并定位
                            let or3dwAry = this.getStrAry(userData[p_r3dw]);
                            changeobj[p_r3dw] = this.megreAry(or3dwAry, or1dwAry).join(',');
                        }
                        else {
                            // 跟r3也不相等，再见，r1 背丢弃
                        }
                    }
                    else {
                        // 如果 r3 为空，直接把之前的r1盖到r3
                        changeobj[p_r3] = or;
                        changeobj[p_r3dw] = ordw;
                    }
                }
            }
            else {
                // 如果 r2 为空，直接把之前的r1盖到r2
                changeobj[p_r2] = or;
                changeobj[p_r2dw] = ordw;
            }
        }

        return changeobj;
    }

    static pathxj(min: number, max: number, posAry: number[][]) {

        if (posAry.length === 0) return true;
        let minpos: number, maxpos: number;
        for (let i = 0; i < posAry.length; i++) {
            minpos = posAry[i][0];
            maxpos = posAry[i][1];

            if ((max > minpos && max < maxpos) || (min > minpos && min < maxpos) || (min < minpos && max > maxpos)) {
                return false;
            }
        }
        return true;

    }

    static resverseKW(str: string): string {
        if (!str) return "";
        let ary = str.split(",");
        let result = ary.reverse().join(",") + "," + 0;
        return result;
    }

    static getGMTHolesToKongPoint(holes: any[], kongpoint: number[], type: number = 2,
        xfu: boolean = false, yfu: boolean = false, xyReverse: boolean = false, callBack: Function = null) {
        if (!kongpoint || !holes) return;
        let callBackdata: any[]
        let x: number, y: number, tmp: number;
        for (let i = 0; i < holes.length; i++) {
            x = holes[i].curves[0].aX;
            y = holes[i].curves[0].aY;

            x = xfu ? -x : x;
            y = yfu ? -y : y;

            if (xyReverse) {
                tmp = x;
                x = y;
                y = tmp;
            }

            if (callBack) {
                callBackdata = callBack(x, y)
                kongpoint.push(...callBackdata);
            }
            else {
                if (type === 0) {
                    kongpoint.push(0, x, y)
                }
                else if (type === 1) {
                    kongpoint.push(x, 0, y)
                }
                else if (type === 2) {
                    kongpoint.push(x, y, 0)
                }
            }

        }
    }

    static getCornerTopFacePos(mesh: MoldMesh, localPoint: Vector3) {
        let outer = mesh.meshType == EntityCreateType.OutCornerCShapeSlot;
        let data = mesh.userData;
        let ZYL = +data.zyL;
        let ZYW = +data.zyW;
        let YYL = +data.yyL;
        let YYW = +data.yyW;
        let BKH = +data.BKH;
        let iszywequal = ZYW === 50 && YYW === 50;
        let szyw = iszywequal ? BKH + ZYW : ZYW;
        let syyw = iszywequal ? BKH + YYW : YYW;
        let angle = (data.p_jiajiao !== 0 && data.p_jiajiao % 180 === 0) ? data.p_jiajiao - 0.001 : data.p_jiajiao;
        let radian = outer ? (360 - angle) / 180 * Math.PI : angle / 180 * Math.PI;
        let cosA = Math.cos(radian);
        let sinA = Math.sin(radian);
        let path = CommonUtils.getCornerPath(0, syyw, szyw, ZYL, YYL, sinA, cosA);
        let start = new Vector3(path[0].x, 0, path[0].y);
        let end = new Vector3(path[1].x, 0, path[1].y);
        let pp = VectorUtils.getProjectVector(start, end, localPoint);
        let yval = pp.distanceTo(start);
        let xval = localPoint.distanceTo(pp);
        let polygon = [
            path[0],
            path[1],
            path[2],
            path[3]
        ];

        let tarpoint = new Vector2(localPoint.x, localPoint.z);
        let pinpolygon = VectorUtils.pointInPolygon(tarpoint, polygon);
        let tag = pinpolygon ? 4 : 5;
        if (!pinpolygon) {
            yval = Math.abs(localPoint.x);
            xval = Math.abs(localPoint.z);
        }

        return [xval, yval, tag];
    }

    static getXieHolesData(r: string, rpos: string, rag: number, sinA: number, cosA: number,
        gmldir: Vector2, gmwdir: Vector2, normal: Vector3) {

        let holes = [];
        CommonUtils.getXieHoles(r, rpos, holes, rag, sinA, cosA, gmldir, gmwdir);
        let tho = []
        for (let i = 0; i < holes.length; i++) {
            tho.push(holes[i].curves[0].aX, 0, holes[i].curves[0].aY)
        }
        return { rad: r, holes: tho, dir: [normal.x, normal.y, normal.z] };

    }


    static getHolesData(r: string, dw: string, type: number, normal: Vector3, isreverse: boolean = false, isY: boolean = false) {

        let holes = [];
        CommonUtils.getGmtHoles(r, dw, holes, type, isreverse);
        let tho = []
        for (let i = 0; i < holes.length; i++) {
            if (isreverse) {
                tho.push(holes[i].curves[0].aX, holes[i].curves[0].aY, 0)
            } else if (isY) {
                tho.push(holes[i].curves[0].aX, 0, holes[i].curves[0].aY);
            }
            else {

                type === 1 ? tho.push(0, holes[i].curves[0].aX, holes[i].curves[0].aY) :
                    type === 0 ? tho.push(holes[i].curves[0].aX, holes[i].curves[0].aY, 0) :
                        null;
            }

        }
        return { rad: r, holes: tho, dir: [normal.x, normal.y, normal.z] };

    }

    static getCHolesData(r: string, dw: string, sinA: number, cosA: number, normal: Vector3, isZ: boolean = false) {

        let holes = [];
        if (isZ) {
            CommonUtils.getGmtHoles(r, dw, holes, 1);
        }
        else {
            CommonUtils.getGmtHoles(r, dw, holes, 1, true);
        }

        let tho = []
        for (let i = 0; i < holes.length; i++) {
            if (isZ) {
                tho.push(holes[i].curves[0].aX * sinA, holes[i].curves[0].aX * cosA, holes[i].curves[0].aY);
            } else {
                tho.push(holes[i].curves[0].aX * cosA, holes[i].curves[0].aY, holes[i].curves[0].aX * sinA);
            }
        }
        return { rad: r, holes: tho, dir: [normal.x, normal.y, normal.z] };

    }

    static getFaceByPaths(count: number, vertices: any[], indices: any[], facevec: any[], frontPath: Vector2[], backPath: Vector2[], holes: Path[],
        type: number, min: number, max: number, reverse: boolean, kongtype: string, sidereverse: boolean = false, createtop: boolean = true) {
        let topface = [];
        let bottomface = [];
        let topvec = [];
        let bottomvec = [];

        let top: Vector3;
        let bottom: Vector3;
        for (let i = 0; i < frontPath.length; i++) {

            top = type === 1 ? new Vector3(max, frontPath[i].x, frontPath[i].y) :
                type === 2 ? new Vector3(frontPath[i].x, max, frontPath[i].y) :
                    new Vector3(frontPath[i].x, frontPath[i].y, max);

            bottom = type === 1 ? new Vector3(min, backPath[i].x, backPath[i].y) :
                type === 2 ? new Vector3(backPath[i].x, min, backPath[i].y) :
                    new Vector3(backPath[i].x, backPath[i].y, min);

            topface.push(top);
            bottomface.push(bottom);
        }

        topvec = sidereverse ? bottomface.concat(bottomface[0].clone()) : topface.concat(topface[0].clone());
        bottomvec = sidereverse ? topface.concat(topface[0].clone()) : bottomface.concat(bottomface[0].clone());

        if (!BIM.simpleMold) {
            // 侧边
            let side = CommonUtils.getSideVIF(topvec, bottomvec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];
        }

        let shape: Shape;
        let geometry: any;
        let position: any;
        let index: any;
        if (!BIM.simpleMold) {
            // 前后面
            shape = new Shape().setFromPoints(frontPath);
            // 挖孔
            if (holes && holes.length > 0) {
                let tmpholes = CommonUtils.getHoleByDivisions(holes);
                shape.holes.push(...tmpholes);
            }

            geometry = CommonUtils.getShapeData(shape);
            position = geometry[0];
            index = geometry[1];

            count = CommonUtils.getShapeFaceVI(count, vertices, indices, facevec, topface, position, index, max, kongtype, type, reverse);
        }

        shape = new Shape().setFromPoints(backPath);
        if (holes && holes.length > 0) {
            let tmpholes = CommonUtils.getHoleByDivisions(holes);
            shape.holes.push(...tmpholes);
        }

        geometry = CommonUtils.getShapeData(shape);
        position = geometry[0];
        index = geometry[1];

        shape = null;

        count = CommonUtils.getShapeFaceVI(count, vertices, indices, facevec, bottomface, position, index, min, kongtype, type, !reverse);

        return count;
    }


    static getXieShapeFaceVI(count: number, vertices: any[], indices: any[], facevec: any[], face: any[],
        sinA: number, cosA: number, xie: number, posAry: any, idxAry: any, max: number, kongtype: string, type: number = 0, reverse: boolean = false): number {
        // 顶点
        let vertex: any[] = []
        let index: any[] = [];

        let adv = xie === 0 ? -cosA : cosA
        for (let i = 0; i < posAry.length; i += 3) {

            let a = posAry[i];
            let b = posAry[i + 1];
            let c = posAry[i + 2];
            type === 1 ? vertex.push(max + b * adv, a, b * sinA) :
                type === 2 ? vertex.push(a, max + a * cosA, b) :
                    vertex.push(a * sinA, b, max + a * adv);
        }

        // 索引
        for (let i = 0; i < idxAry.length; i += 3) {
            let a = idxAry[i] + count;
            let b = idxAry[i + 1] + count;
            let c = idxAry[i + 2] + count;

            index.push(a, b, c);
        }

        reverse ? index.reverse() : null;
        vertices.push(...vertex);
        indices.push(...index);
        kongtype ? facevec.push({ key: kongtype, faces: [...face] }) : facevec.push(face);

        count = Math.max(...indices) + 1;

        return count;
    }

    static getXieShapeVI(count: number, vertices: any[], indices: any[], facevec: any[], frontPath: Vector2[], backPath: Vector2[], holes: Path[],
        sinA: number, cosA: number, xie: number, type: number, min: number, max: number, reverse: boolean, kongtype: string, sidereverse: boolean = false, createtop: boolean = true): number {

        let topface = [];
        let bottomface = [];
        let topvec = [];
        let bottomvec = [];

        let top: Vector3;
        let bottom: Vector3;
        let adv = xie === 0 ? - cosA : cosA; // 0 内斜 否则 外斜

        for (let i = 0; i < frontPath.length; i++) {

            top = type === 1 ? new Vector3(max + frontPath[i].y * adv, frontPath[i].x, frontPath[i].y * sinA) :
                type === 2 ? new Vector3(frontPath[i].x, max, frontPath[i].y) :
                    new Vector3(frontPath[i].x * sinA, frontPath[i].y, max + frontPath[i].x * adv);

            bottom = type === 1 ? new Vector3(min + backPath[i].y * adv, backPath[i].x, backPath[i].y * sinA) :
                type === 2 ? new Vector3(backPath[i].x, min, backPath[i].y) :
                    new Vector3(backPath[i].x * sinA, backPath[i].y, min + backPath[i].x * adv);

            topface.push(top);
            bottomface.push(bottom);
        }

        topvec = sidereverse ? bottomface.concat(bottomface[0].clone()) : topface.concat(topface[0].clone());
        bottomvec = sidereverse ? topface.concat(topface[0].clone()) : bottomface.concat(bottomface[0].clone());

        if (!BIM.simpleMold) {
            // 侧边
            let side = CommonUtils.getSideVIF(topvec, bottomvec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];
        }


        // 前后面
        let shape = new Shape().setFromPoints(frontPath);
        // 挖孔
        if (holes && holes.length > 0) {

            let tmpholes = CommonUtils.getHoleByDivisions(holes);
            shape.holes.push(...tmpholes);
        }

        let geometry = CommonUtils.getShapeData(shape);
        let position = geometry[0];
        let index = geometry[1];

        shape = null;

        count = CommonUtils.getXieShapeFaceVI(count, vertices, indices, facevec, topface, sinA, cosA, xie, position, index, max, kongtype, type, reverse);
        // //geometry.dispose();


        if (!BIM.simpleMold) {
            if (createtop) {

                // 前后面
                shape = new Shape().setFromPoints(backPath);
                // 挖孔
                if (holes && holes.length > 0) {
                    let tmpholes = CommonUtils.getHoleByDivisions(holes);
                    shape.holes.push(...tmpholes);
                }

                geometry = CommonUtils.getShapeData(shape);
                position = geometry[0];
                index = geometry[1];

                shape = null;
                count = CommonUtils.getXieShapeFaceVI(count, vertices, indices, facevec, bottomface, sinA, cosA, xie, position, index, min, kongtype, type, !reverse);
                // //geometry.dispose();
            }
        }


        return count;
    }

    static getFaceVI(topvec: Vector3[], bottomvec: Vector3[], count: number, istop: boolean = false): any[] {

        let vertex: number[] = [];
        let index: number[] = [];
        let face: Vector3[] = [];
        let faceVec: any[] = [];

        for (let i = 0; i < bottomvec.length - 1; i++) {

            vertex.push(bottomvec[i].x, bottomvec[i].y, bottomvec[i].z);
            vertex.push(bottomvec[i + 1].x, bottomvec[i + 1].y, bottomvec[i + 1].z);

            vertex.push(topvec[i].x, topvec[i].y, topvec[i].z);
            vertex.push(topvec[i + 1].x, topvec[i + 1].y, topvec[i + 1].z);

            if (istop) {
                index.push(count + i, count + i + 2, count + i + 1);
                index.push(count + i + 2, count + i + 3, count + i + 1);
            }
            else {
                index.push(count + i, count + i + 1, count + i + 2);
                index.push(count + i + 2, count + i + 1, count + i + 3);
            }

            // 面
            face = [];
            face.push(bottomvec[i], bottomvec[i + 1], topvec[i + 1], topvec[i]);
            faceVec.push(face);

            count += 3;
        }

        count += bottomvec.length - 1;


        return [vertex, index, faceVec, count];
    }

    /**
    * 根据类型修改数据
    * @param type 
    * @param ZYL 左翼长
    * @param xAxis 要修正的x值
    * @param cosA 余弦值
    * @param sinA 正弦值
    * @returns 
    */
    static getXZ(type: number, ZYL: number, xAxis: number, cosA: number, sinA: number) {
        let x = xAxis;
        let z = 0;
        if (type === 0) {

            x = xAxis * sinA + ZYL * cosA;
            z = -xAxis * cosA + ZYL * sinA;
        }
        else if (type === 1) {
            x = xAxis * cosA;
            z = xAxis * sinA;
        }
        else if (type === 2) {
            x = xAxis * sinA + ZYL * cosA;
            z = xAxis * cosA - ZYL * sinA;
        }
        return [x, z];
    }


    /**
   * 获取左侧斜封板的数据
   * @param count 
   * @param vertices 
   * @param indices 
   * @param facevec 
   * @param type 
   * @param ZYL 左翼长
   * @param BKH 封板厚度
   * @param cosA 夹角
   * @param sinA 夹角
   * @param topface 上坐标 封边
   * @param bottomface 下坐标 用于封边
   * @param path 路径
   * @param holes 洞
   * @param reverse 是否翻转索引
   * @returns 
   */
    static getFengVI(count: number, vertices: any[], indices: any[], facevec: any[],
        ZYL: number, BKH: number, cosA: number, sinA: number,
        topface: Vector3[], bottomface: Vector3[], path: Vector2[], holes: Path[], kongtype: string, type: number = 0, reverse: boolean = false) {

        let topvec = topface.concat(topface[0].clone());
        let bottomvec = bottomface.concat(bottomface[0].clone());

        if (!BIM.simpleMold) {
            // 侧边
            let side = CommonUtils.getSideVIF(bottomvec, topvec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];

        }

        // 形状
        let shape = new Shape().setFromPoints(path);
        // 挖孔
        if (holes && holes.length > 0) {

            let tmpholes = CommonUtils.getHoleByDivisions(holes);
            shape.holes.push(...tmpholes);
            // shape.holes.push(...holes);
        }

        let geometry = CommonUtils.getShapeData(shape);
        let positionAry = geometry[0];
        let indexAry = geometry[1];
        shape = null;
        // 顶点
        let vertex: any[] = []
        let index: any[] = [];

        for (let i = 0; i < positionAry.length; i += 3) {

            let a = positionAry[i];
            let b = positionAry[i + 1];
            let c = positionAry[i + 2];

            let xz = CommonUtils.getXZ(type, ZYL, a, cosA, sinA);

            vertex.push(xz[0], b, xz[1]);
        }

        // 索引
        for (let i = 0; i < indexAry.length; i += 3) {
            let a = indexAry[i] + count;
            let b = indexAry[i + 1] + count;
            let c = indexAry[i + 2] + count;

            index.push(a, b, c);
        }

        reverse ? index.reverse() : null;
        vertices.push(...vertex);
        indices.push(...index);
        kongtype ? facevec.push({ key: kongtype, faces: [...topface.concat()] }) : facevec.push(topface.concat());

        count = Math.max(...indices) + 1;

        if (!BIM.simpleMold) {
            vertex = [];
            index = [];
            for (let i = 0; i < positionAry.length; i += 3) {

                let a = positionAry[i];
                let b = positionAry[i + 1];
                let c = positionAry[i + 2];

                let xz = CommonUtils.getXZ(type, ZYL - BKH, a, cosA, sinA);
                vertex.push(xz[0], b, xz[1]);

            }

            // 索引
            for (let i = 0; i < indexAry.length; i += 3) {
                let a = indexAry[i] + count;
                let b = indexAry[i + 1] + count;
                let c = indexAry[i + 2] + count;

                index.push(a, b, c);
            }

            reverse ? null : index.reverse();
            vertices.push(...vertex);
            indices.push(...index);

            kongtype ? facevec.push({ key: kongtype, faces: [...bottomface.concat()] }) : facevec.push(bottomface.concat());

            count = Math.max(...indices) + 1;
        }

        return count;
    }

    /**
    * 获取左斜的距离
    * @param zh 左宽
    * @param yh 右宽
    * @param sinA 
    * @param cosA 
    * @returns 
    */
    static getLeftXieVi(zh: number, yh: number, zyl: number, sinA: number, cosA: number): any[] {

        let p1 = new Vector2(zh / sinA + yh / sinA * cosA, yh);
        let p2 = new Vector2(zh * sinA + zyl * cosA, zyl * sinA - zh * cosA);
        let dis = p1.distanceTo(p2);
        return [p1, p2, dis];
    }

    static getLeftXieFaceVI(zh: number, yh: number, zyl: number, miny: number, maxy: number, sinA: number, cosA: number, xie: number = 0) {
        return [
            new Vector3(zh / sinA + yh / sinA * cosA, maxy, yh),
            new Vector3(zh / sinA + yh / sinA * cosA, miny, yh),
            new Vector3(zh * sinA + (zyl + xie) * cosA, miny, (zyl + xie) * sinA - zh * cosA),
            new Vector3(zh * sinA + zyl * cosA, maxy, zyl * sinA - zh * cosA)
        ]
    }


    /**
   * 获取右背面
   * @param count 
   * @param vertices 
   * @param indices 
   * @param facevec 
   * @param holes 
   * @param bx 
   * @param tx 
   * @param maxx 
   * @param miny 
   * @param maxy 
   * @param minz 
   * @param maxz 
   * @returns 
   */
    static getRightHoleVI(count: number, vertices: any[], indices: any[], facevec: any[], holes: Path[],
        bx: number, tx: number, bmaxx: number, tmaxx: number, miny: number, maxy: number, minz: number, maxz: number,
        cosA: number, sinA: number, ZYW: number, YYW: number, kongtype: string, leftxie: number = 0): number {

        // 后
        let backpath = [
            new Vector2(bx, maxy),
            new Vector2(bx, miny),
            new Vector2(bmaxx + leftxie, miny),
            new Vector2(bmaxx, maxy)
        ]

        let backface = [
            new Vector3(bx, maxy, minz),
            new Vector3(bx, miny, minz),
            new Vector3(bmaxx + leftxie, miny, minz),
            new Vector3(bmaxx, maxy, minz)
        ]

        //前 
        let fontpath = [
            new Vector2(tx, maxy),
            new Vector2(tx, miny),
            new Vector2(tmaxx + leftxie, miny),
            new Vector2(tmaxx, maxy)
        ];

        let frontface = [
            new Vector3(tx, maxy, maxz),
            new Vector3(tx, miny, maxz),
            new Vector3(tmaxx + leftxie, miny, maxz),
            new Vector3(tmaxx, maxy, maxz)
        ]

        count = CommonUtils.getHolePathFace(count, vertices, indices, facevec, fontpath, holes, frontface, cosA, sinA, ZYW, YYW, maxz, kongtype, 0, true);
        if (BIM.simpleMold) return count;

        count = CommonUtils.getHolePathFace(count, vertices, indices, facevec, backpath, holes, backface, cosA, sinA, ZYW, YYW, minz, kongtype, 0);


        // 封边
        // 顶点
        vertices.push(backface[3].x, backface[3].y, backface[3].z);
        vertices.push(backface[2].x, backface[2].y, backface[2].z);

        vertices.push(frontface[3].x, frontface[3].y, frontface[3].z);
        vertices.push(frontface[2].x, frontface[2].y, frontface[2].z);

        // 索引
        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        count += 4;

        // 下
        vertices.push(backface[2].x, backface[2].y, backface[2].z);
        vertices.push(backface[1].x, backface[1].y, backface[1].z);

        vertices.push(frontface[2].x, frontface[2].y, frontface[2].z);
        vertices.push(frontface[1].x, frontface[1].y, frontface[1].z);

        // 索引
        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        count += 4;

        vertices.push(backface[0].x, backface[0].y, backface[0].z);
        vertices.push(backface[3].x, backface[3].y, backface[3].z);

        vertices.push(frontface[0].x, frontface[0].y, frontface[0].z);
        vertices.push(frontface[3].x, frontface[3].y, frontface[3].z);

        // 索引
        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        count += 4;

        return count;
    }


    /**
  * 根据路径和洞，获取带孔的面数据
  * @param count 
  * @param vertices 
  * @param indices 
  * @param facevec 
  * @param path 
  * @param holes 
  * @param face 
  * @param isreverse 
  * @returns 
  */
    static getHolePathFace(count: number, vertices: any[], indices: any[], facevec: any[], path: Vector2[], holes: Path[], face: Vector3[],
        cosA: number, sinA: number, ZYW: number, YYW: number, zv: number, kongtype: string, type: number = 0, isreverse: boolean = false): number {
        let shape = new Shape().setFromPoints(path);
        // 挖孔
        if (holes && holes.length > 0) {
            let tmpholes = CommonUtils.getHoleByDivisions(holes);
            shape.holes.push(...tmpholes);
        }

        let vertex: any[] = []
        let index: any[] = [];

        let geometry = CommonUtils.getShapeData(shape);
        let positionAry = geometry[0];
        let indexAry = geometry[1];
        for (let i = 0; i < positionAry.length; i += 3) {

            let a = positionAry[i];
            let b = positionAry[i + 1];
            let c = positionAry[i + 2];

            type === 1 ? vertex.push(a * cosA + ZYW / sinA + YYW / sinA * cosA, b, a * sinA + YYW) :
                type === 2 ? vertex.push(a * cosA + ZYW / sinA + YYW / sinA * cosA, b, a * sinA + YYW) :
                    vertex.push(a, b, zv);
        }

        // 索引
        for (let i = 0; i < indexAry.length; i += 3) {
            let a = indexAry[i] + count;
            let b = indexAry[i + 1] + count;
            let c = indexAry[i + 2] + count;

            index.push(a, b, c);
        }

        !isreverse ? index.reverse() : null;
        vertices.push(...vertex);
        indices.push(...index);
        kongtype ? facevec.push({ key: kongtype, faces: [...face.concat()] }) : facevec.push(face.concat());

        count = Math.max(...indices) + 1;
        //geometry.dispose();

        return count;
    }

    /**
* 带孔的左斜板
* @param count 
* @param vertices 
* @param indices 
* @param facevec 
* @param holes 
* @param backpath 
* @param fontpath 
* @param backface 
* @param frontface 
* @param ZYW 左宽
* @param YYW 右宽
* @param BKH 厚度
* @param sinA 
* @param cosA 
* @returns 
*/
    static getLeftHoleVI(count: number, vertices: any[], indices: any[], facevec: any[], bholes: Path[], fholes: Path[],
        backpath: Vector2[], fontpath: Vector2[], backface: Vector3[], frontface: Vector3[],
        ZYW: number, YYW: number, BKH: number, sinA: number, cosA: number, kongtype: string): number {

        // 后
        count = CommonUtils.getHolePathFace(count, vertices, indices, facevec, fontpath, fholes, frontface, cosA, sinA, ZYW, YYW, 0, kongtype, 2, false);

        count = CommonUtils.getHolePathFace(count, vertices, indices, facevec, backpath, bholes, backface, cosA, sinA, ZYW - BKH, YYW - BKH, 0, kongtype, 1, true);


        // 封边
        // 顶点
        vertices.push(backface[2].x, backface[2].y, backface[2].z);
        vertices.push(backface[3].x, backface[3].y, backface[3].z);

        vertices.push(frontface[2].x, frontface[2].y, frontface[2].z);
        vertices.push(frontface[3].x, frontface[3].y, frontface[3].z);
        // 索引
        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        count += 4;

        // 底边
        vertices.push(backface[1].x, backface[1].y, backface[1].z);
        vertices.push(backface[2].x, backface[2].y, backface[2].z);

        vertices.push(frontface[1].x, frontface[1].y, frontface[1].z);
        vertices.push(frontface[2].x, frontface[2].y, frontface[2].z);
        // 索引
        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        count += 4;
        // 顶边
        vertices.push(backface[3].x, backface[3].y, backface[3].z);
        vertices.push(backface[0].x, backface[0].y, backface[0].z);

        vertices.push(frontface[3].x, frontface[3].y, frontface[3].z);
        vertices.push(frontface[0].x, frontface[0].y, frontface[0].z);
        // 索引
        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        count += 4;

        return count;
    }

    /**
   * 获取圆柱体数据
   * @param count 
   * @param vertices 
   * @param indices 
   * @param facevec 
   * @param x 长向定位
   * @param y 宽向偏移
   * @param zr 直径
   * @param miny 
   * @param maxy 
   * @returns 
   */
    static getCylinderVI(count: number, vertices: any[], indices: any[], facevec: any[],
        x: number, y: number, zr: number, miny: number, maxy: number, ir: number = 2, needTop: boolean = false, neednei: boolean = true): number {

        // 段数
        let i: number, pot: Vector2, ver: Vector2[];
        let segment: number = 6;

        // 外圈
        let shape = new Shape()
            .moveTo(0, 0)
            .absarc(0, 0, zr / 2, 0, Math.PI * 2, true);

        let shapePoints = shape.extractPoints(segment);

        ver = shapePoints.shape;
        let reverse = !ShapeUtils.isClockWise(ver);
        if (reverse) {
            ver = ver.reverse();
        }

        let topVec: Vector3[] = [];
        let bottomVec: Vector3[] = [];
        for (i = 0; i < ver.length; i++) {
            pot = ver[i];
            topVec.push(new Vector3(pot.x + x, maxy, pot.y + y));
            bottomVec.push(new Vector3(pot.x + x, miny, pot.y + y));
        }

        let side = CommonUtils.getSideVIF(bottomVec, topVec, count);
        vertices.push(...side[0]);
        indices.push(...side[1]);
        facevec.push(...side[2]);
        count = side[3];
        shape = null;
        if (neednei) {
            // 内圈
            shape = new Shape()
                .moveTo(0, 0)
                .absarc(0, 0, zr / 2 - ir, 0, Math.PI * 2, true);
            shapePoints = shape.extractPoints(segment);
            ver = shapePoints.shape;
            reverse = !ShapeUtils.isClockWise(ver);

            if (reverse) {
                ver = ver.reverse();
            }

            let itopVec: Vector3[] = [];
            let ibottomVec: Vector3[] = [];
            for (i = 0; i < ver.length; i++) {
                pot = ver[i];
                itopVec.push(new Vector3(pot.x + x, maxy, pot.y + y));
                ibottomVec.push(new Vector3(pot.x + x, miny, pot.y + y));
            }

            side = CommonUtils.getSideVIF(itopVec, ibottomVec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];

            // 底面
            side = CommonUtils.getSideVIF(ibottomVec, bottomVec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];

            if (needTop) {
                side = CommonUtils.getSideVIF(itopVec, topVec, count);
                vertices.push(...side[0]);
                indices.push(...side[1]);
                facevec.push(...side[2]);
                count = side[3];
            }
            shape = null;
        }



        return count;
    }

    static checkPointPolygon(points: Vector2[], p: Vector2) {
        let count = 0;
        let p1 = points[0];
        for (var i = 1; i < points.length; i++) { //遍历整个点
            var p2 = points[i];
            if (p.y > Math.min(p1.y, p2.y) && p.y <= Math.max(p1.y, p2.y)) { //纵坐标在范围之内

                if (p.x <= Math.max(p1.x, p2.x)) { //横坐标小于最大值
                    if (p1.y != p2.y) {
                        var temp_x = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;

                        if (p1.x == p2.x || p.x <= temp_x)
                            count++;
                    }
                }
            }
            p1 = p2;
        }

        if (count % 2) {
            return true;
        } else {
            return false;
        }
    }

    static inPolygon(point: Vector2, polygon: Vector2[], r: number): boolean {

        let i: number, dis: number;
        let cross: Vector2[] = [];
        let vec = polygon.concat(polygon[0])
        for (i = 0; i < vec.length; i++) {
            // 相交
            dis = vec[i].distanceTo(point);
            if (dis < r) {
                return false;
            }
        }
        return true;
    }

    /**
    * 获取 夹角形状的坐标 \__
    * @param fh 
    * @param sh 
    * @param zyl 
    * @param yyl 
    * @param sinA 
    * @param cosA 
    * @returns 
    */
    static getCornerPath(fh: number, yh: number, zh: number, zyl: number, yyl: number, sinA: number, cosA: number, fu: boolean = false) {
        let path = fu ? [
            new Vector2(fh / sinA + fh / sinA * cosA, -fh),
            new Vector2(fh * sinA + zyl * cosA, -zyl * sinA + fh * cosA),

            new Vector2(zh * sinA + zyl * cosA, -zyl * sinA + zh * cosA),
            new Vector2(zh / sinA + yh / sinA * cosA, -yh),

            new Vector2(yyl, -yh),
            new Vector2(yyl, -fh)
        ] : [
            new Vector2(fh / sinA + fh / sinA * cosA, fh),
            new Vector2(fh * sinA + zyl * cosA, zyl * sinA - fh * cosA),

            new Vector2(zh * sinA + zyl * cosA, zyl * sinA - zh * cosA),
            new Vector2(zh / sinA + yh / sinA * cosA, yh),

            new Vector2(yyl, yh),
            new Vector2(yyl, fh)
        ]

        return path;
    }

    static getCapsulePath(one: Vector2, two: Vector2, r: number, istop: boolean = false): Path {
        let result: Path;

        let center = one.clone().add(two).multiplyScalar(0.5);

        let rad = Math.sin(Math.PI / 4);

        if (istop) {
            result = new Path()
                .moveTo(center.x, center.y)
                .absarc(one.x, one.y, r, Math.PI * 0.25, Math.PI * 1.25, false)
                .lineTo(two.x - rad * r, two.y - rad * r)
                .absarc(two.x, two.y, r, Math.PI * 1.25, Math.PI * 0.25, false)
                .lineTo(one.x + rad * r, one.y + rad * r);
        }
        else {
            result = new Path()
                .moveTo(center.x, center.y)
                .absarc(one.x, one.y, r, Math.PI * 1.75, Math.PI * 0.75, false)
                .lineTo(two.x - rad * r, two.y + rad * r)
                .absarc(two.x, two.y, r, Math.PI * 0.75, Math.PI * 1.75, false)
                .lineTo(one.x + rad * r, one.y - rad * r);
        }

        return result;
    }

    static getVectorMinX(a: Vector2[], b: Vector2[], isy: boolean = false): number[] {
        let c = a.concat(b);
        let xv: number[] = [];
        for (let i = 0; i < c.length; i++) {
            isy ? xv.push(c[i].y) : xv.push(c[i].x);
        }
        let max = Math.max.apply(Math, xv);
        let min = Math.min.apply(Math, xv);
        return [max, min];

    }

    static getQKAry(qkdw: string, len: number) {
        let result: number[] = [];
        let i: number = 0;
        // 先查找下有没有*
        qkdw += '';
        let idx = qkdw.indexOf('*');
        if (idx === -1) {
            // 没有 *
            let dary = qkdw.split(',');
            let ev: number = 0;
            for (i = 0; i < dary.length; i++) {
                ev = Number(dary[i]);
                if (ev > 0) {
                    result.push(ev);
                }
            }
            return result;
        }
        else {
            // 有* 看下是否符合规范
            let ary = qkdw.split('*');
            if (ary[1] !== "") {
                return result;
            }

            let one = Number(ary[0]);
            if (one > 0) {
                let average = Math.floor(len / one);
                average = len % one === 0 ? average - 1 : average;
                for (i = 0; i < average; i++) {
                    result.push(one);
                }
                return result;
            }
            else {
                return result;
            }
        }

    }

    static haveData(data: Vector2[][]): boolean {
        for (let i = 0; i < data.length; i++) {
            if (data[i].length > 0) {
                return true;
            }
        }
        return false;
    }

    static SqrtValue(a: number, b: number): number {
        return Math.sqrt(a ** 2 + b ** 2);
    }

    static isPathZero(path: Vector2[]) {
        for (let i = 0; i < path.length; i++) {
            if (path[i].x < 0) {
                return true;
            }
        }

        return false;
    }

    static getSideFace(count: number, vertices: any[], indices: any[], facevec: any[],
        topface: Vector3[], bottomface: Vector3[], reverse: boolean = false): number {

        let topVec = reverse ? bottomface.concat(bottomface[0].clone()) : topface.concat(topface[0].clone());
        let bottomVec = reverse ? topface.concat(topface[0].clone()) : bottomface.concat(bottomface[0].clone());

        // 侧边
        let side = CommonUtils.getSideVIF(topVec, bottomVec, count);
        vertices.push(...side[0]);
        indices.push(...side[1]);
        facevec.push(...side[2]);
        count = side[3];

        return count;
    }

    static getVIF(bottomVec: Vector3[], topVec: Vector3[], vertexCount: number = 0): any[] {

        let face: Vector3[];

        let faceVec: any[] = [];
        let vertex: any[] = [];
        let index: any[] = [];

        // 侧面
        for (let i = 0; i < bottomVec.length - 1; i++) {
            // 顶点
            vertex.push(topVec[i].x, topVec[i].y, topVec[i].z);
            vertex.push(topVec[i + 1].x, topVec[i + 1].y, topVec[i + 1].z);

            vertex.push(bottomVec[i].x, bottomVec[i].y, bottomVec[i].z);
            vertex.push(bottomVec[i + 1].x, bottomVec[i + 1].y, bottomVec[i + 1].z);
            // 索引
            index.push(vertexCount + i, vertexCount + i + 2, vertexCount + i + 1);
            index.push(vertexCount + i + 2, vertexCount + i + 3, vertexCount + i + 1);
            // 面
            face = [];
            face.push(topVec[i], topVec[i + 1], bottomVec[i + 1], bottomVec[i]);
            faceVec.push(face);

            vertexCount += 3;
        }
        // 底面
        vertexCount += bottomVec.length - 1;

        vertex.push(bottomVec[0].x, bottomVec[0].y, bottomVec[0].z);
        vertex.push(bottomVec[1].x, bottomVec[1].y, bottomVec[1].z);
        vertex.push(bottomVec[3].x, bottomVec[3].y, bottomVec[3].z);
        vertex.push(bottomVec[2].x, bottomVec[2].y, bottomVec[2].z);

        index.push(vertexCount, vertexCount + 2, vertexCount + 1);
        index.push(vertexCount + 2, vertexCount + 3, vertexCount + 1);

        face = [];
        face.push(bottomVec[0], bottomVec[1], bottomVec[2], bottomVec[3]);
        faceVec.push(face);

        vertexCount += 4;
        vertex.push(topVec[0].x, topVec[0].y, topVec[0].z);
        vertex.push(topVec[1].x, topVec[1].y, topVec[1].z);
        vertex.push(topVec[3].x, topVec[3].y, topVec[3].z);
        vertex.push(topVec[2].x, topVec[2].y, topVec[2].z);

        index.push(vertexCount, vertexCount + 1, vertexCount + 2);
        index.push(vertexCount + 2, vertexCount + 1, vertexCount + 3);

        face = [];
        face.push(topVec[0], topVec[1], topVec[2], topVec[3]);
        faceVec.push(face);

        vertexCount += 4;

        return [vertex, index, faceVec, vertexCount];

    }

    static getCuboidVI(count: number, vertices: any[], indices: any[], facevec: any[],
        minx: number, maxx: number, miny: number, maxy: number, minz: number, maxz: number, side: boolean = false): number {

        let topface = [
            new Vector3(minx, miny, minz),
            new Vector3(minx, miny, maxz),
            new Vector3(maxx, miny, maxz),
            new Vector3(maxx, miny, minz),
            new Vector3(minx, miny, minz)
        ]

        let bottomface = [
            new Vector3(minx, maxy, minz),
            new Vector3(minx, maxy, maxz),
            new Vector3(maxx, maxy, maxz),
            new Vector3(maxx, maxy, minz),
            new Vector3(minx, maxy, minz)
        ]

        let vi = side ? CommonUtils.getSideVIF(topface, bottomface, count) : CommonUtils.getVIF(topface, bottomface, count);

        vertices.push(...vi[0]);
        indices.push(...vi[1]);
        facevec.push(...vi[2]);
        count = vi[3];

        return count;
    }

    static dealHole(kongpoint: number[], callBack: Function): number[] {

        let newData: number[];
        for (let i = 0; i < kongpoint.length; i += 3) {
            newData = callBack(kongpoint[i], kongpoint[i + 1], kongpoint[i + 2]);
            kongpoint[i] = newData[0];
            kongpoint[i + 1] = newData[1];
            kongpoint[i + 2] = newData[2];
        }

        return kongpoint;
    }

    static getShapeFaceVI(count: number, vertices: any[], indices: any[], facevec: any[], face: any[],
        posAry: any, idxAry: any, max: number, kongtype: string, type: number = 0, reverse: boolean = false): number {
        // 顶点
        let vertex: any[] = []
        let index: any[] = [];

        for (let i = 0; i < posAry.length; i += 3) {

            let a = posAry[i];
            let b = posAry[i + 1];
            let c = posAry[i + 2];
            type === 1 ? vertex.push(max, a, b) :
                type === 2 ? vertex.push(a, max, b) :
                    vertex.push(a, b, max);
        }

        // 索引
        for (let i = 0; i < idxAry.length; i += 3) {
            let a = idxAry[i] + count;
            let b = idxAry[i + 1] + count;
            let c = idxAry[i + 2] + count;

            index.push(a, b, c);
        }

        reverse ? index.reverse() : null;
        vertices.push(...vertex);
        indices.push(...index);
        kongtype ? facevec.push({ key: kongtype, faces: [...face.concat()] }) : facevec.push(face.concat());

        count = Math.max(...indices) + 1;

        return count;
    }


    static getXieQieShapeVI(count: number, vertices: any[], indices: any[], facevec: any[], path: Vector2[], holes: Path[], topface: Vector3[], bottomface: Vector3[],
        type: number, min: number, max: number, reverse: boolean, kongtype: string, createtop: boolean = true): number {
        // 前后面
        let shape = new Shape().setFromPoints(path);
        // 挖孔
        if (holes && holes.length > 0) {
            let tmpholes = CommonUtils.getHoleByDivisions(holes);
            shape.holes.push(...tmpholes);
        }

        let geometry = CommonUtils.getShapeData(shape);
        let position = geometry[0];
        let index = geometry[1];
        shape = null;

        count = CommonUtils.getShapeFaceVI(count, vertices, indices, facevec, topface, position, index, max, kongtype, type, reverse);
        if (createtop) {
            count = CommonUtils.getShapeFaceVI(count, vertices, indices, facevec, bottomface, position, index, min, kongtype, type, !reverse);
        }
        // //geometry.dispose();


        return count;
    }

    /**
     * 获取形状组成的物体，可带孔
     * @param count 索引
     * @param vertices 顶点数组
     * @param indices 索引数组
     * @param facevec 面数组
     * @param path 形状路径
     * @param holes 洞路径
     * @param type 类型 0 z 1 x 2 y
     * @param min 最小值
     * @param max 最大值
     * @param reverse 是否颠倒索引
     * @param sidereverse 是否颠倒边
     * @returns 
     */
    static getShapeVI(count: number, vertices: any[], indices: any[], facevec: any[], path: Vector2[], holes: Path[],
        type: number, min: number, max: number, reverse: boolean, kongtype: string, sidereverse: boolean = false, createtop: boolean = true): number {

        let topface = [];
        let bottomface = [];
        let topvec = [];
        let bottomvec = [];

        let top: Vector3;
        let bottom: Vector3;
        for (let i = 0; i < path.length; i++) {

            top = type === 1 ? new Vector3(max, path[i].x, path[i].y) :
                type === 2 ? new Vector3(path[i].x, max, path[i].y) :
                    new Vector3(path[i].x, path[i].y, max);

            bottom = type === 1 ? new Vector3(min, path[i].x, path[i].y) :
                type === 2 ? new Vector3(path[i].x, min, path[i].y) :
                    new Vector3(path[i].x, path[i].y, min);

            topface.push(top);
            bottomface.push(bottom);
        }

        topvec = sidereverse ? bottomface.concat(bottomface[0].clone()) : topface.concat(topface[0].clone());
        bottomvec = sidereverse ? topface.concat(topface[0].clone()) : bottomface.concat(bottomface[0].clone());

        // 侧边

        let side = CommonUtils.getSideVIF(topvec, bottomvec, count);
        vertices.push(...side[0]);
        indices.push(...side[1]);
        facevec.push(...side[2]);
        count = side[3];

        count = CommonUtils.getXieQieShapeVI(count, vertices, indices, facevec, path, holes, topface, bottomface, type, min, max, reverse, kongtype, createtop);

        return count;
    }

    static getXieHoles(r: string, rpos: string, holes: Path[], rag: number,
        sinA: number, cosA: number, gmdlir: Vector2, gmwdir: Vector2) {
        let holePath: Path;
        let cdr: string[];
        let index: number = -1;
        let i: number, xv: number, yv: number, widthR: number, hightR: number, gmtR: number;
        let gmtpos = AModelFmulaUtils.getHolesbyExpress(rpos, 0, 3);

        let centeV: Vector2 = new Vector2();

        let fcp: Vector2, scp: Vector2;
        let fsp: Vector2, fep: Vector2;
        let ssp: Vector2, sep: Vector2;

        if (gmtpos && gmtpos.length > 0) {
            for (i = 0; i < gmtpos.length; i++) {

                xv = gmtpos[i].x;
                yv = gmtpos[i].y;

                centeV.set(xv, yv);

                index = r.toString().indexOf('*');
                if (index != -1) {
                    cdr = r.split('*');
                    widthR = Number(cdr[0]);
                    hightR = Number(cdr[1]);

                    gmtR = widthR > hightR ? hightR : widthR;

                    holePath = new Path();
                    if (widthR > hightR) {

                        fcp = centeV.clone().sub(gmdlir.clone().setLength((widthR - hightR) / 2));
                        scp = centeV.clone().add(gmdlir.clone().setLength((widthR - hightR) / 2));

                        fsp = fcp.clone().sub(gmwdir.clone().setLength(hightR / 2));
                        fep = fcp.clone().add(gmwdir.clone().setLength(hightR / 2));


                        ssp = scp.clone().sub(gmwdir.clone().setLength(hightR / 2));
                        sep = scp.clone().add(gmwdir.clone().setLength(hightR / 2));


                        holePath.moveTo(xv, yv)
                            .absarc(fcp.x, fcp.y, gmtR / 2, rag + Math.PI / 2, rag - Math.PI / 2, false)
                            .lineTo(sep.x, sep.y)
                            .absarc(scp.x, scp.y, gmtR / 2, rag - Math.PI / 2, rag + Math.PI / 2, false)
                            .lineTo(fsp.x, fsp.y)
                    }
                    else {

                        fcp = centeV.clone().sub(gmwdir.clone().setLength((-widthR + hightR) / 2));
                        scp = centeV.clone().add(gmwdir.clone().setLength((-widthR + hightR) / 2));

                        fsp = fcp.clone().sub(gmdlir.clone().setLength(widthR / 2));
                        fep = fcp.clone().add(gmdlir.clone().setLength(widthR / 2));


                        ssp = scp.clone().sub(gmdlir.clone().setLength(widthR / 2));
                        sep = scp.clone().add(gmdlir.clone().setLength(widthR / 2));

                        holePath.moveTo(xv, yv)
                            .absarc(fcp.x, fcp.y, gmtR / 2, rag, Math.PI + rag, false)
                            .lineTo(ssp.x, ssp.y)
                            .absarc(scp.x, scp.y, gmtR / 2, Math.PI + rag, rag, false)
                            .lineTo(fep.x, fep.y)
                    }
                }
                else {
                    gmtR = Number(r);

                    holePath = new Path();
                    holePath.moveTo(xv, yv)
                        .absarc(xv, yv, gmtR / 2, 0, Math.PI * 2, true);
                }
                holes.push(holePath);
            }
        }
    }

    /**
   * 获取光面孔
   * @param r 
   * @param rpos 
   * @param holes 
   * @param type 0 x 1 y 2 z
   */
    static getGmtHoles(r: string, rpos: string, holes: Path[],
        type: number = 0, yfu: boolean = false, cvx: number = 0, cvy: number = 0,
        centres: Vector3[] = null, xfu: boolean = false): void {

        if (!r || r === "" || !rpos || rpos === "") return;

        let holePath: Path;
        let cdr: string[];
        let index: number = -1;
        let i: number, xv: number, yv: number, widthR: number, hightR: number, gmtR: number;
        let gmtpos = AModelFmulaUtils.getHolesbyExpress(rpos, 0, 3);

        if (gmtpos && gmtpos.length > 0) {
            for (i = 0; i < gmtpos.length; i++) {

                xv = type === 1 ? gmtpos[i].y : gmtpos[i].x;
                yv = type === 1 ? gmtpos[i].x : gmtpos[i].y;
                yv = yfu ? -yv : yv;
                xv = xfu ? -xv : xv;

                xv += cvx;
                yv += cvy;

                index = r.toString().indexOf('*');
                if (index != -1) {
                    cdr = r.split('*');
                    if (type === 1) {
                        widthR = Number(cdr[0]);
                        hightR = Number(cdr[1]);
                    }
                    else {
                        widthR = Number(cdr[1]);
                        hightR = Number(cdr[0]);
                    }


                    gmtR = widthR > hightR ? hightR : widthR;

                    holePath = new Path();
                    if (widthR > hightR) {
                        holePath.moveTo(xv, yv)
                            .absarc(xv + (widthR - hightR) / 2, yv, gmtR / 2, Math.PI * 1.5, Math.PI * 0.5, false)
                            .lineTo(xv - (widthR - hightR) / 2, yv + hightR / 2)
                            .absarc(xv - (widthR - hightR) / 2, yv, gmtR / 2, Math.PI * 0.5, Math.PI * 1.5, false)
                            .lineTo(xv + (widthR - hightR) / 2, yv - hightR / 2)
                    }
                    else {
                        holePath.moveTo(xv, yv)
                            .absarc(xv, yv + (hightR - widthR) / 2, gmtR / 2, 0, Math.PI, false)
                            .lineTo(xv - widthR / 2, yv - (hightR - widthR) / 2)
                            .absarc(xv, yv - (hightR - widthR) / 2, gmtR / 2, Math.PI, Math.PI * 2, false)
                            .lineTo(xv + widthR / 2, yv + (hightR - widthR) / 2)
                    }
                }
                else {
                    gmtR = Number(r);

                    holePath = new Path();
                    holePath.moveTo(xv, yv)
                        .absarc(xv, yv, gmtR / 2, 0, Math.PI * 2, true);
                }
                if (centres) centres.push(new Vector3(xv, yv));
                holes.push(holePath);
            }
        }

    }


    static getPointToLineMinDistance(point: Vector2, polygon: Vector2[], r: number) {

        let line: Vector3 = new Vector3(point.x, point.y, 0);
        let PP: Vector3, start: Vector3, end: Vector3;
        let sdir: Vector3, edir: Vector3;
        let sdis: number, edis: number;
        let disAry = [];
        let dis: number;
        start = new Vector3();
        end = new Vector3();
        for (let i = 0; i < polygon.length; i++) {

            if (i === polygon.length - 1) {
                start.set(polygon[i].x, polygon[i].y, 0);
                end.set(polygon[0].x, polygon[0].y, 0);

            }
            else {
                start.set(polygon[i].x, polygon[i].y, 0);
                end.set(polygon[i + 1].x, polygon[i + 1].y, 0);

            }
            PP = VectorUtils.getProjectVector(start, end, line);
            dis = line.distanceTo(PP);
            if (dis < r) {
                // 算下点是否在线上
                sdir = PP.clone().sub(start);
                edir = PP.clone().sub(end);

                if (VectorUtils.isDirectionSame(sdir, edir)) {
                    // 如果同向说明不在线上
                    sdis = PP.distanceTo(start);
                    edis = PP.distanceTo(end);

                    disAry.push(sdis, edis);
                    continue;
                }

            }
            disAry.push(dis);
        }

        return Math.min(...disAry);
    }

    static getRadius(r: string): number {

        let idx = r.indexOf('*');
        if (idx === -1) {
            return Number(r) * 0.5;
        }
        else {
            let rAry = r.split('*');
            let zuo = Number(rAry[0]);
            let you = Number(rAry[1]);
            let tmpAry = [];
            if (!isNaN(zuo)) {
                tmpAry.push(zuo);
            }
            if (!isNaN(you)) {
                tmpAry.push(you);
            }

            return Math.max(...tmpAry) * 0.5;
        }
    }

    /**
     * 检测半径是否合法
     * @param checkR 
     * @returns 
     */
    static checkRadiusIsLegal(checkR: string) {

        if (!checkR || checkR == "") return "";
        let regex = /^(\d+(\.\d+)?|\d*\.\d+)(\*\d+(\.\d+)?)?$/;
        let isLegal = regex.test(checkR);
        if (!isLegal) {
            return "";
        }
        return checkR;
    }

    static hasSameVector(v: Vector2, result: Vector2[]): boolean {
        for (let j = 0; j < result.length; j++) {
            if (result[j].equals(v)) {
                return true;
            }
        }
        return false;
    }

    static filterRepeatArray(path: Vector2[]): Vector2[] {
        let result: Vector2[] = [path[0]]
        for (let i = 1; i < path.length; i++) {
            if (!CommonUtils.hasSameVector(path[i], result)) {
                result.push(path[i]);
            }
        }
        return result;
    }

    static checkHoleInFace(tmp: Vector2, polygon: Vector2[], r: string = '10') {
        let pinpolygon = VectorUtils.pointInPolygon(tmp, polygon);
        if (pinpolygon) {
            // 算下孔位
            // 算下孔到边的最近距离
            let mindis = CommonUtils.getPointToLineMinDistance(tmp, polygon, CommonUtils.getRadius(r));
            if (mindis > CommonUtils.getRadius(r)) {
                return true;
            }
        }
        return false;
    }

    /**
  * 过滤掉超出光面的孔位,面孔参数定位dw自动加括号()，面孔UI自动加括号
  * @param dw 
  * @param polygon 
  * @returns 
  */
    static fliterOuterPoint(dw: string, polygon: Vector2[],
        isreverse: boolean = false, yfu: boolean = false, xfu: boolean = false,
        checkR: boolean = true, r: string = '10'): string {

        if (!dw) return "";

        let result: string = ''
        let gmtpos = AModelFmulaUtils.getHolesbyExpress(dw, 0, 3);
        if (gmtpos.length > 0) {
            gmtpos = CommonUtils.filterRepeatArray(gmtpos);
        }
        let tmp: Vector2 = new Vector2();
        for (let i = 0; i < gmtpos.length; i++) {

            if (isreverse) {
                tmp.set(gmtpos[i].y, gmtpos[i].x);
            }
            else {
                tmp.set(gmtpos[i].x, gmtpos[i].y);
            }
            yfu ? tmp.setY(-tmp.y) : tmp;
            xfu ? tmp.setX(-tmp.x) : tmp;
            let pinpolygon = VectorUtils.pointInPolygon(tmp, polygon);
            if (pinpolygon) {
                // 算下孔位
                if (checkR) {
                    // 算下孔到边的最近距离
                    let mindis = CommonUtils.getPointToLineMinDistance(tmp, polygon, CommonUtils.getRadius(r)+10);
                    if (mindis < CommonUtils.getRadius(r) + 10) {
                        continue;
                    }
                }

                result += '(' + gmtpos[i].x + ',' + gmtpos[i].y + ")" + ","
            }
        }

        if (gmtpos.length > 0 && result === '') {
            return "";
        }

        let checkStr: string = result === '' ? dw : result;

        // 过滤下非 （num,num）形式的面孔输入
        if (checkStr && checkStr != "") {

            let regexp = /\([-+]?(\d+(\.\d*)?|\.\d+),\s*[-+]?(\d+(\.\d*)?|\.\d+)\)/g;
            let array = [...checkStr.matchAll(regexp)]
            if (array.length > 0) {
                let allary = []
                for (let ii = 0; ii < array.length; ii++) {
                    allary.push(array[ii][0]);
                }
                return allary.join(",")
            }
            else {
                return "";
            }
        }

        //zjj 清除孔位得时候保留原值
        if (gmtpos.length < 1) {
            return dw;
        }

        return result.substring(0, result.length - 1);
    }

    /**
     * 求面孔距离光面四边的最小距离
     */
    static computeHolesMinDis(dw: string, polygon: Vector2[],
        isreverse: boolean = false, yfu: boolean = false, xfu: boolean = false,
        checkR: boolean = false, r: string = '20'): number {

        let result: number[] = [];
        let gmtpos = AModelFmulaUtils.getHolesbyExpress(dw, 0, 3);
        let tmp: Vector2 = new Vector2();
        for (let i = 0; i < gmtpos.length; i++) {

            if (isreverse) {
                tmp.set(gmtpos[i].y, gmtpos[i].x);
            }
            else {
                tmp.set(gmtpos[i].x, gmtpos[i].y);
            }
            yfu ? tmp.setY(-tmp.y) : tmp;
            xfu ? tmp.setX(-tmp.x) : tmp;

            // 算下孔到边的最近距离
            let mindis = CommonUtils.getPointToLineMinDistance(tmp, polygon, CommonUtils.getRadius(r));

            result.push(mindis);
        }

        return Math.min(...result);
    }

    static addVectorFaceVI(count: number, vertices: number[], indices: number[], facevec: any[], fontface: Vector3[], kongtype?: string): number {
        // 顶
        vertices.push(fontface[0].x, fontface[0].y, fontface[0].z);
        vertices.push(fontface[1].x, fontface[1].y, fontface[1].z);
        vertices.push(fontface[3].x, fontface[3].y, fontface[3].z);
        vertices.push(fontface[2].x, fontface[2].y, fontface[2].z);

        indices.push(count, count + 2, count + 1);
        indices.push(count + 2, count + 3, count + 1);

        kongtype ? facevec.push({ key: kongtype, faces: [fontface[0], fontface[1], fontface[2], fontface[3]] }) : facevec.push([fontface[0], fontface[1], fontface[2], fontface[3]]);
        count += 4;

        return count;
    }

    /**通过数据得到圆的v和i
     * 圆的半径，默认为1
     * 圆的分段数，默认为32
     * 圆弧的起始角度，默认为0
     * 圆弧的弧长，默认为2π
     */
    static getCirclePath(radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2) {
        const indices = [];
        const vertices = [];

        vertices.push(0, 0, 0);

        const vertex = new Vector3();
        for (let s = 0, i = 3; s <= segments; s++, i += 3) {

            const segment = thetaStart + s / segments * thetaLength;

            // vertex

            vertex.x = radius * Math.cos(segment);
            vertex.y = radius * Math.sin(segment);

            vertices.push(vertex.x, vertex.y, vertex.z);

            // normal

            // normals.push( 0, 0, 1 );

            // uvs

            // uv.x = ( vertices[ i ] / radius + 1 ) / 2;
            // uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;

            // uvs.push( uv.x, uv.y );
        }

        // indices

        for (let i = 1; i <= segments; i++) {

            indices.push(i, i + 1, 0);
        }

        return [vertices, indices];
    }

    static getHoleByDivisions(holes: Path[]): Path[] {
        let divisions = 6;
        let result: Path[] = [];
        let expoints: Vector2[];
        for (let hole of holes) {
            expoints = hole.getPoints(divisions)
            result.push(new Path(expoints))
        }
        return result;
    }

    static getShapeData(shape: Shape, curveSegments = 12) {

        const indices = [];
        const vertices = [];
        // const normals = [];
        // const uvs = [];

        const indexOffset = vertices.length / 3;
        const points = shape.extractPoints(curveSegments);

        let shapeVertices = points.shape;
        const shapeHoles = points.holes;

        // check direction of vertices

        if (ShapeUtils.isClockWise(shapeVertices) === false) {

            shapeVertices = shapeVertices.reverse();

        }

        for (let i = 0, l = shapeHoles.length; i < l; i++) {

            const shapeHole = shapeHoles[i];

            if (ShapeUtils.isClockWise(shapeHole) === true) {
                shapeHoles[i] = shapeHole.reverse();
            }

        }

        const faces = ShapeUtils.triangulateShape(shapeVertices, shapeHoles);

        // join vertices of inner and outer paths to a single array

        for (let i = 0, l = shapeHoles.length; i < l; i++) {

            const shapeHole = shapeHoles[i];
            shapeVertices = shapeVertices.concat(shapeHole);

        }

        // vertices, normals, uvs

        for (let i = 0, l = shapeVertices.length; i < l; i++) {

            const vertex = shapeVertices[i];
            vertices.push(vertex.x, vertex.y, 0);
            // normals.push(0, 0, 1);
            // uvs.push(vertex.x, vertex.y); // world uvs
        }

        // indices
        for (let i = 0, l = faces.length; i < l; i++) {

            const face = faces[i];

            const a = face[0] + indexOffset;
            const b = face[1] + indexOffset;
            const c = face[2] + indexOffset;

            indices.push(a, b, c);

        }

        return [vertices, indices];
    }

    static getFaceByGeometry(count: number, vertices: number[], indices: number[], facevec: any[],
        face: Vector3[], geometry: any, kongtype: string, fuc: Function): number {

        let position = geometry[0];
        let index = geometry[1];

        let vertex: any[] = []
        let idxAry: any[] = [];

        for (let i = 0; i < position.length; i += 3) {

            let a = position[i];
            let b = position[i + 1];
            let c = position[i + 2];
            let xyz = fuc(a, b);
            vertex.push(xyz[0], xyz[1], xyz[2]);
        }

        // 索引
        for (let i = 0; i < index.length; i += 3) {
            let a = index[i] + count;
            let b = index[i + 1] + count;
            let c = index[i + 2] + count;

            idxAry.push(a, b, c);
        }

        vertices.push(...vertex);
        indices.push(...idxAry);
        kongtype ? facevec.push({ key: kongtype, faces: [...face] }) : facevec.push(face);

        count = Math.max(...indices) + 1;

        return count;
    }

    static getFaceByFunction(count: number, vertices: number[], indices: number[], facevec: Vector3[][],
        face: Vector3[], path: Vector2[], holePath: Path[], kongtype: string, fuc: Function): number {

        if (!path || path.length == 0) {
            console.log("模型路径有问题")
            return count;
        }

        let shape = new Shape().setFromPoints(path);
        // 挖孔

        if (holePath && holePath.length > 0) {
            let tmpholes = CommonUtils.getHoleByDivisions(holePath);
            shape.holes.push(...tmpholes);
        }

        let geometry = CommonUtils.getShapeData(shape);
        count = CommonUtils.getFaceByGeometry(count, vertices, indices, facevec, face, geometry, kongtype, fuc);
        shape = null;
        // geometry.dispose();

        return count;
    }

    /**
    * 获取侧边数据
    * @param bottomVec 底面数组 
    * @param topVec 顶部数组
    * @param vertexCount 索引值
    * @returns 
    */
    static getSideVIF(bottomVec: Vector3[], topVec: Vector3[], vertexCount: number): any[] {
        let face: Vector3[];

        let faceVec: any[] = [];
        let vertex: any[] = [];
        let index: any[] = [];

        // 侧面
        for (let i = 0; i < bottomVec.length - 1; i++) {
            // 顶点
            vertex.push(topVec[i].x, topVec[i].y, topVec[i].z);
            vertex.push(topVec[i + 1].x, topVec[i + 1].y, topVec[i + 1].z);

            vertex.push(bottomVec[i].x, bottomVec[i].y, bottomVec[i].z);
            vertex.push(bottomVec[i + 1].x, bottomVec[i + 1].y, bottomVec[i + 1].z);
            // 索引
            index.push(vertexCount + i, vertexCount + i + 2, vertexCount + i + 1);
            index.push(vertexCount + i + 2, vertexCount + i + 3, vertexCount + i + 1);
            // 面
            face = [];
            face.push(topVec[i], topVec[i + 1], bottomVec[i + 1], bottomVec[i]);
            faceVec.push(face);

            vertexCount += 3;
        };

        vertexCount += bottomVec.length - 1;

        return [vertex, index, faceVec, vertexCount];
    }

    /**圆柱的数据vetices和indexs */
    static getYuanzhuVI(count: number, vertices: number[], indices: number[], facevec: Vector3[][], min: number, max: number, r: number, type: number = 0, needTB: boolean = true): number {
        // 段数
        let i: number, pot: Vector2, ver: Vector2[];
        let segment: number = 4;

        // 外圈
        let shape = new Shape()
            .moveTo(0, 0)
            .absarc(0, 0, r, 0, Math.PI * 2, true);

        let shapePoints = shape.extractPoints(segment);

        ver = shapePoints.shape;
        let reverse = !ShapeUtils.isClockWise(ver);
        if (reverse) {
            ver = ver.reverse();
        }

        let topVec: Vector3[] = [];
        let bottomVec: Vector3[] = [];
        let top: Vector3, bottom: Vector3;
        for (i = 0; i < ver.length; i++) {
            pot = ver[i];

            top = type === 1 ? new Vector3(pot.x, min, pot.y) :
                type === 2 ? new Vector3(pot.x, pot.y, min) :
                    new Vector3(min, pot.x, pot.y);
            bottom = type === 1 ? new Vector3(pot.x, max, pot.y) :
                type === 2 ? new Vector3(pot.x, pot.y, max) :
                    new Vector3(max, pot.x, pot.y);

            topVec.push(top);
            bottomVec.push(bottom);
        }

        let side = CommonUtils.getSideVIF(bottomVec, topVec, count);
        vertices.push(...side[0]);
        indices.push(...side[1]);
        facevec.push(...side[2]);
        count = side[3];

        if (needTB) {
            // 顶底
            let geometry = CommonUtils.getCirclePath(r, segment * 2);
            count = CommonUtils.getFaceByGeometry(count, vertices, indices, facevec, [], geometry, null, (a: number, b: number) => type === 1 ? [a, min, b] : type === 2 ? [a, b, min] : [min, a, b]);
            count = CommonUtils.getFaceByGeometry(count, vertices, indices, facevec, [], geometry, null, (a: number, b: number) => type === 1 ? [a, max, b] : type === 2 ? [a, b, max] : [max, a, b]);
            // geometry.dispose();
        }
        shape = null;
        return count;
    }


    static getShapeFunctionVI(count: number, vertices: any[], indices: any[], facevec: any[], path: Vector2[], holes: Path[], kongtype: string, kongpoint: number[],
        tfacefunc: Function, bfacefunc: Function, tvecfunc: Function, bvecfunc: Function, kongfunc: Function = null): number {

        let topface = [];
        let bottomface = [];
        let topvec = [];
        let bottomvec = [];

        // 面数据
        for (let i = 0; i < path.length; i++) {
            topface.push(tfacefunc(path[i].x, path[i].y));
            bottomface.push(bfacefunc(path[i].x, path[i].y));
        }

        topvec = topface.concat(topface[0].clone());
        bottomvec = bottomface.concat(bottomface[0].clone());

        // 前面
        count = CommonUtils.getFaceByFunction(count, vertices, indices, facevec, topface, path, holes, kongtype, tvecfunc);

        if (!BIM.simpleMold) {
            // 侧边
            let side = CommonUtils.getSideVIF(topvec, bottomvec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];
            // 后面
            count = CommonUtils.getFaceByFunction(count, vertices, indices, facevec, bottomface, path, holes, kongtype, bvecfunc);
        }

        if (kongfunc) {
            kongpoint.push(...kongfunc())
        }

        return count;
    }


    static getShapeFunctionVIByPaths(count: number, vertices: any[], indices: any[], facevec: any[],
         tpath: Vector2[], tholes: Path[],bpath: Vector2[], bholes: Path[], kongtype: string, kongpoint: number[],
        tfacefunc: Function, bfacefunc: Function, tvecfunc: Function, bvecfunc: Function, kongfunc: Function = null): number {

        let topface = [];
        let bottomface = [];
        let topvec = [];
        let bottomvec = [];

        // 面数据
        for (let i = 0; i < tpath.length; i++) {
            topface.push(tfacefunc(tpath[i].x, tpath[i].y));
            bottomface.push(bfacefunc(bpath[i].x, bpath[i].y));
        }

        topvec = topface.concat(topface[0].clone());
        bottomvec = bottomface.concat(bottomface[0].clone());

        // 前面
        count = CommonUtils.getFaceByFunction(count, vertices, indices, facevec, topface, tpath, tholes, kongtype, tvecfunc);

        if (!BIM.simpleMold) {
            // 侧边
            let side = CommonUtils.getSideVIF(topvec, bottomvec, count);
            vertices.push(...side[0]);
            indices.push(...side[1]);
            facevec.push(...side[2]);
            count = side[3];
            // 后面
            count = CommonUtils.getFaceByFunction(count, vertices, indices, facevec, bottomface, bpath, bholes, kongtype, bvecfunc);
        }

        if (kongfunc) {
            kongpoint.push(...kongfunc())
        }

        return count;
    }

}